Skip to content

Better types from jsdoc type references #16316

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 8, 2017
Merged

Better types from jsdoc type references #16316

merged 4 commits into from
Jun 8, 2017

Conversation

rbuckton
Copy link
Contributor

@rbuckton rbuckton commented Jun 7, 2017

Previously, if the symbol for the type reference could not be resolved to a type and the symbol pointed to a value, we would just get the type of the symbol. However, this practice results in the wrong type for a JavaScript constructor function.

With this change, we now try to follow the value symbol across CommonJS require calls to get the correct symbol. If the resulting symbol is a JavaScript constructor function, we return the inferred class type for the symbol. Otherwise, we fall back to the previous behavior.

Fixes #14056

@rbuckton rbuckton requested review from mhegazy and a user June 7, 2017 01:18
@@ -6814,37 +6814,58 @@ namespace ts {
return undefined;
}

function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName) {
function resolveTypeReferenceName(node: TypeReferenceType, typeReferenceName: EntityNameExpression | EntityName) {
Copy link

@ghost ghost Jun 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is only called in one location. At that location, we have special handling for JSDocTypeReference already. So maybe we should just avoid calling resolveTypeReferenceName from that code path altogether instead of adding special-casing for jsdoc here. Same for getTypeReferenceName.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original logic had a lot of duplication. The logic here was performing the same steps as the logic here. This change merely routes the code through the same path. However, I could make a change to pass in the meaning instead of computing it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, getPrimitiveTypeFromJSDocTypeReference may return undefined if the jsdoc type was not a primitive type name, thus even JSDocTypeReference nodes will call this function.

}

function getTypeReferenceType(node: TypeReferenceType, symbol: Symbol) {
const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced.
let secondPass = true;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can we be on the second pass already?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...which is why the test is failing. Last minute typo :/

}

function getTypeReferenceType(node: TypeReferenceType, symbol: Symbol) {
const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced.
let secondPass = true;
let fallbackType: Type = unknownType;
while (true) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this loop has a maximum of 2 iterations, couldn't you just define a function and call it twice?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could. I could also call this function recursively. This approach avoids call stack allocation since I reuse the current stack frame.

return getTypeFromNonGenericTypeReference(node, symbol);
// Try to use the symbol of the type (if present) to get a better type on the
// second pass.
fallbackType = getTypeOfSymbol(symbol);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intended to allow:

const x = new Foo();
// Equivalent to @return {Foo}
/** @return {x} */
function f() { return x; }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to continue to be reported as an error, but we will fall back to the type of the value as per the existing comment.

@rbuckton rbuckton merged commit 0760439 into master Jun 8, 2017
@rbuckton rbuckton deleted the fix14056 branch June 8, 2017 00:30
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

JSDoc Does not Pick up Type imported using Require
3 participants